package com.alinesno.cloud.common.web.base.controller;

import java.util.List;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.alinesno.cloud.base.boot.feign.dto.ManagerAccountDto;
import com.alinesno.cloud.common.facade.feign.BaseDto;
import com.alinesno.cloud.common.facade.feign.IBaseFeign;
import com.alinesno.cloud.common.facade.wrapper.RestWrapper;
import com.alinesno.cloud.common.web.base.bean.DatatablesPageBean;
import com.alinesno.cloud.common.web.base.form.FormToken;
import com.alinesno.cloud.common.web.base.response.ResponseBean;
import com.alinesno.cloud.common.web.base.response.ResponseGenerator;
import com.alinesno.cloud.common.web.login.aop.AccountRecord;
import com.alinesno.cloud.common.web.login.aop.AccountRecord.RecordType;
import com.alinesno.cloud.common.web.login.session.CurrentAccountSession;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;

/**
 * 基础操作层
 * @author LuoAnDong
 * @since 2018年12月23日 下午12:21:42
 */
public abstract class FeignMethodController<DTO extends BaseDto , FEIGN extends IBaseFeign<DTO>> extends BaseController {

	protected CopyOptions copyOptions = new CopyOptions().setIgnoreNullValue(true) ; 

	private static final Logger log = LoggerFactory.getLogger(FeignMethodController.class) ; 
	protected ObjectMapper objectMapper = new ObjectMapper();  
	
	@Autowired
	protected FEIGN feign ; 

	/**
	 * 查询所有，数据过滤
	 * @param feign
	 * @param applicationId
	 * @return
	 */
	@SuppressWarnings("unused")
	protected List<DTO> findAll(FEIGN feign , String applicationId) {
		ManagerAccountDto account = CurrentAccountSession.get(request) ;
		RestWrapper restWrapper = new RestWrapper().eq("", "") ; 
		
		List<DTO> list = feign.findAll(restWrapper) ; 
		return list ; 
	}
	
	protected DatatablesPageBean toPage(Model model, FEIGN feign, DatatablesPageBean page) {
		
		// ----------------------- 兼容bootstrap table_start ---------------
		if(page.isBootstrapTable()) {
			page.setStart(page.getPageNum()-1);
			page.setLength(page.getPageSize());
		}
		// ----------------------- 兼容bootstrap table_end ---------------
		
		RestWrapper restWrapper = new RestWrapper() ; 
		restWrapper.setPageNumber(page.getStart());
		restWrapper.setPageSize(page.getLength());
		
		log.debug("===> DatatablesPageBean:{}" , JSONObject.toJSON(page));
		
		restWrapper.builderCondition(page.getCondition()) ; 
		
		Page<DTO> pageableResult = feign.findAllByWrapperAndPageable(restWrapper) ; 
		
		// DatatablesPageBean p = new DatatablesPageBean();
		
		if(page.isBootstrapTable()) {
			// ----------------------- 兼容bootstrap table_start ---------------
			page.setRows(pageableResult.getContent());
			page.setTotal((int) pageableResult.getTotalElements());
			page.setCode(HttpStatus.OK.value()); 
			// ----------------------- 兼容bootstrap table_end ---------------
		} else {
			page.setData(pageableResult.getContent());
			page.setDraw(page.getDraw());
			page.setRecordsFiltered((int) pageableResult.getTotalElements());
			page.setRecordsTotal((int) pageableResult.getTotalElements());
		}
		
		return page ;
	}
	
	@GetMapping("/list")
    public void list(){
    }

	/**
	 * 菜单管理查询功能  
	 * @return
	 */
	@AccountRecord(type=RecordType.ACCESS_ADD)
	@FormToken(save=true)
	@GetMapping("/add")
    public void add(Model model , HttpServletRequest request){
    }
	
	
	/**
	 * 保存新对象 
	 * @param model
	 * @param managerCodeDto
	 * @return
	 */
	@AccountRecord(type=RecordType.OPERATE_SAVE)
	@FormToken(remove=true)
	@ResponseBody
	@PostMapping("/save")
	public ResponseBean save(Model model , HttpServletRequest request, DTO dto) {
		log.debug("===> save dto:{}" , ToStringBuilder.reflectionToString(dto));
		
		dto = feign.save(dto) ; 
		return ResponseGenerator.ok(null) ; 	
	}
	
	
	/**
	 * 删除
	 */
//	@AccountRecord(type=RecordType.OPERATE_DELETE)
//	@ResponseBody
//	@PostMapping("/delete")
//    public ResponseBean delete(@RequestParam(value = "rowsId[]") String[] rowsId){
//		log.debug("rowsId = {}" , ToStringBuilder.reflectionToString(rowsId));
//		if(rowsId != null && rowsId.length > 0) {
//			feign.deleteByIds(rowsId); 
//		}
//		return ResponseGenerator.ok(null) ; 
//    }
	
	/**
	 * 删除
	 */
	@AccountRecord(type=RecordType.OPERATE_DELETE)
	@ResponseBody
	@GetMapping("/delete")
    public ResponseBean delete(String ids){
		log.debug("delete ids:{}" , ids);
		
		String[] rowsId = ids.split(",") ; 
		if (rowsId != null && rowsId.length > 0) {
			feign.deleteByIds(rowsId);
		}
		return ResponseGenerator.ok(null);
    }
	

	/**
	 * 详情
	 */
	@AccountRecord(type=RecordType.OPERATE_QUERY)
	@ResponseBody
	@GetMapping("/detailJson")
    public ResponseBean detail(String id){
		log.debug("id = {}" , id);
		Optional<DTO> bean = feign.findById(id) ; 
		return bean.isPresent()?ResponseGenerator.ok(bean.get()):ResponseGenerator.fail("") ; 
    }

	/**
	 * 保存
	 * @param model
	 * @param request
	 * @param managerApplicationDto
	 * @return
	 */
	@AccountRecord(type=RecordType.OPERATE_UPDATE)
	@FormToken(remove=true)
	@ResponseBody
	@PostMapping("/update")
	public ResponseBean update(Model model , HttpServletRequest request, DTO dto) {
		
		if(dto != null && StringUtils.isNotBlank(dto.getId())) {
			
			DTO oldBean = feign.getOne(dto.getId()) ; 
			BeanUtil.copyProperties(dto, oldBean ,CopyOptions.create().setIgnoreNullValue(true));
			
			oldBean = feign.save(oldBean) ; 
			return ResponseGenerator.ok(null) ; 	
			
		}else {
			return this.save(model, request, dto) ; 
		}
	}

	/**
	 * 查询所有
	 * @param applicationId
	 * @return
	 */
	@ResponseBody
	@GetMapping("findAll")
	public List<DTO> findAll(){
		return feign.findAll() ; 
	}

	/**
	 * 查询返回实体
	 * @param applicationId
	 * @return
	 */
	@ResponseBody
	@GetMapping("getOne")
	public DTO getOne(@RequestParam("id") String id) {
		return feign.getOne(id) ; 
	}

	/**
	 * 查询统计 
	 * @param applicationId
	 * @return
	 */
	@ResponseBody
	@GetMapping("count")
	public long count() {
		return feign.count() ; 
	}
	
	/**
	 * 删除
	 * @param id
	 */
	@ResponseBody
	@GetMapping("deleteById")
	public void deleteById(@RequestParam("id") String id) {
		feign.deleteById(id); ; 
	}

	/**
	 * 查询所有通过applicationId
	 * @param applicationId
	 * @return
	 */
	@ResponseBody
	@GetMapping("findAllByApplicationId")
	List<DTO> findAllByApplicationId(@RequestParam("applicationId") String applicationId){
		return feign.findAllByTenantId(applicationId) ; 
	}
	
	/**
	 * 查询所有通过applicationId
	 * @param applicationId
	 * @return
	 */
	@ResponseBody
	@GetMapping("findAllByTenantId")
	List<DTO> findAllByTenantId(@RequestParam("tenantId") String tenantId){
		return feign.findAllByTenantId(tenantId) ; 
	}


	/**
	 * 修改功能  
	 * @return
	 */
	@FormToken(save=true)
	@GetMapping("/modify")
    public void modify(HttpServletRequest request ,Model model , String id){
		Assert.hasLength(id , "主键不能为空.");
		DTO code = feign.getOne(id) ; 
		model.addAttribute("bean", code) ; 
    }

	/**
	 * 详情
	 * @return
	 */
	@FormToken(save=true)
	@GetMapping("/detail")
    public void detail(HttpServletRequest request ,Model model , String id){
		Assert.hasLength(id , "主键不能为空.");
		DTO code = feign.getOne(id) ; 
		model.addAttribute("bean", code) ; 
    }
	

	/**
	 * 修改状态
	 * @return
	 */
	@ResponseBody
	@GetMapping("/changeStatus")
    public ResponseBean changeStatus(String id){
		boolean b = feign.modifyHasStatus(id) ; 
		return ResponseGenerator.ok(b) ; 
    }

	
}
